package com.huangfu.learning.javabase.java.pattern.structure.decorator;

/**
 * Created with IntelliJ IDEA.
 * Author: huangfu.daohui
 * Date: 2018/8/8
 * Time: 14:21
 * Version: 1.0
 * Description:装饰器模式：允许向一个现有的对象添加新的功能，同时又不改变其结构。可代替继承
 * https://www.cnblogs.com/zhangtianq/p/6091047.html
 * <p>
 * 优点：装饰类和被装饰类可以独立发展，不会相互耦合，装饰模式是继承的一个替代模式，装饰模式可以动态扩展一个实现类的功能。
 * 缺点：多层装饰比较复杂。
 * <p>
 * 装饰器模式由组件和装饰者组成。
 * 抽象组件（Component）：需要装饰的抽象对象。
 * 具体组件（ConcreteComponent）：是我们需要装饰的对象
 * 抽象装饰类（Decorator）：内含指向抽象组件的引用及装饰者共有的方法。
 * 具体装饰类（ConcreteDecorator）：被装饰的对象。
 * <p>
 * 使用场景： 1、扩展一个类的功能。 2、动态增加功能，动态撤销。
 **/
public class DecoratorPattern {

    // 测试类
    public static void main(String[] args) {

        //汽车的基本功能
        System.out.println("***********汽车的基本功能******************");
        ICar car = new Car();
        car.move();

        System.out.println("***********汽车的飞行功能******************");
        //汽车的飞行功能
        ICar flyCar = new FlyCar(car);
        flyCar.move();

        System.out.println("***********汽车的游泳功能******************");
        // 汽车的游泳功能
        ICar waterCar = new WaterCar(car);
        waterCar.move();

        System.out.println("***********汽车的自动功能******************");
        // 汽车的自动功能
        ICar aiCar = new AICar(car);
        aiCar.move();

        System.out.println("***********汽车的自动飞行双功能******************");
        // 新增两个技能
        ICar two = new AICar(new FlyCar(car));
        two.move();

    }
}

/**
 * 基础接口
 */
interface ICar {
    void move();
}


/**
 * 实现类类
 */
class Car implements ICar {

    @Override
    public void move() {
        System.out.println("汽车具备移动的功能！");
    }
}

/**
 * 装饰基类，跟实现类实现共同的接口
 */
class SuperCar implements ICar{

    private ICar iCar;

    public SuperCar(ICar iCar){
        this.iCar = iCar;
    }
    @Override
    public void move() {
        iCar.move();
    }
}

/**
 * 具体的装饰类,增加新技能
 */
class FlyCar extends SuperCar{

    public FlyCar(ICar iCar) {
        super(iCar);
    }

    // 技能扩展
    public void fly(){
        System.out.println("天上飞！");
    }

    public void move(){
        super.move();
        fly();
    }

}
/**
 * 具体的装饰类,增加新技能
 */
class WaterCar extends SuperCar{

    public WaterCar(ICar car) {
        super(car);
    }

    public void swim(){
        System.out.println("水里游！");
    }

    @Override
    public void move() {
        super.move();
        swim();
    }
}
/**
 * 具体的装饰类,增加新技能
 */
class AICar extends SuperCar{

    public AICar(ICar car) {
        super(car);
    }

    public void autoMove(){
        System.out.println("自动跑！");
    }

    @Override
    public void move() {
        super.move();
        autoMove();
    }
}